﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics;
using System.Reflection;

namespace IRC.IRepairClouds.DataLayer.Expressions
{
    partial class Extensions
    {
        #region Binary Arithmetic Operations

        public static BinaryExpressionBuilder<T> Add<T>(this ExpressionBuilder<T> left, T right)
        {
            return Add<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Add<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Add(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Add<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Add<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Add<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Add(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> AddChecked<T>(this ExpressionBuilder<T> left, T right)
        {
            return AddChecked<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> AddChecked<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.AddChecked(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> AddChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return AddChecked<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> AddChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.AddChecked(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> Divide<T>(this ExpressionBuilder<T> left, T right)
        {
            return Divide<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Divide<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Divide(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Divide<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Divide<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Divide<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Divide(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> Modulo<T>(this ExpressionBuilder<T> left, T right)
        {
            return Modulo<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Modulo<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Modulo(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Modulo<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Modulo<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Modulo<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Modulo(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> Multiply<T>(this ExpressionBuilder<T> left, T right)
        {
            return Multiply<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Multiply<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Multiply(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Multiply<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Multiply<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Multiply<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Multiply(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> MultiplyChecked<T>(this ExpressionBuilder<T> left, T right)
        {
            return MultiplyChecked<T>(left, ExpressionBuilder.Constant<T>( right));
        }
        public static BinaryExpressionBuilder<T> MultiplyChecked<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.MultiplyChecked(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> MultiplyChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return MultiplyChecked<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> MultiplyChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.MultiplyChecked(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> Power<T>(this ExpressionBuilder<T> left, T right)
        {
            return Power(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Power<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Power(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Power<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Power<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Power<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Power(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> Subtract<T>(this ExpressionBuilder<T> left, T right)
        {
            return Subtract<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Subtract<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Subtract(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Subtract<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Subtract<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Subtract<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Subtract(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> SubtractChecked<T>(this ExpressionBuilder<T> left, T right)
        {
            return SubtractChecked<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> SubtractChecked<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.SubtractChecked(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> SubtractChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return SubtractChecked<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> SubtractChecked<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.SubtractChecked(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Bitwise Operations

        private static ExpressionBuilder<T> SkipNull<T>(ExpressionBuilder<T> left, ExpressionBuilder<T> right, Func<Expression, Expression, BinaryExpression> expression)
        {
            if (left == null && right == null)
                return null;
            if (left == null)
                return right;
            if (right == null)
                return left;
            return expression(left, right);//.ToExpressionBuilder<T>();
        }

        public static ExpressionBuilder<T> And<T>(this ExpressionBuilder<T> left, T right)
        {
            return And<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static ExpressionBuilder<T> And<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return SkipNull<T>(left, right, Expression.And);
            //return Expression.And(left, right).ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> And<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return And(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> And<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.And(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static ExpressionBuilder<T> Or<T>(this ExpressionBuilder<T> left, T right)
        {
            return Or<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static ExpressionBuilder<T> Or<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return SkipNull<T>(left, right, Expression.Or);
            //return Expression.Or(left, right).ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Or<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return Or<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> Or<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.Or(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static ExpressionBuilder<T> ExclusiveOr<T>(this ExpressionBuilder<T> left, T right)
        {
            return ExclusiveOr<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static ExpressionBuilder<T> ExclusiveOr<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return SkipNull<T>(left, right, Expression.ExclusiveOr);
            //return Expression.ExclusiveOr(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> ExclusiveOr<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return ExclusiveOr<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> ExclusiveOr<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.ExclusiveOr(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Shift Operations

        public static BinaryExpressionBuilder<T> LeftShift<T>(this ExpressionBuilder<T> left, Int32 right)
        {
            return LeftShift<T>(left, ExpressionBuilder.Constant<Int32>(right));
        }
        public static BinaryExpressionBuilder<T> LeftShift<T>(this ExpressionBuilder<T> left, ExpressionBuilder<Int32> right)
        {
            return Expression.LeftShift(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> LeftShift<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return LeftShift<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> LeftShift<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.LeftShift(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> RightShift<T>(this ExpressionBuilder<T> left, Int32 right)
        {
            return RightShift<T>(left, ExpressionBuilder.Constant<Int32>(right));
        }
        public static BinaryExpressionBuilder<T> RightShift<T>(this ExpressionBuilder<T> left, ExpressionBuilder<Int32> right)
        {
            return Expression.RightShift(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> RightShift<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return RightShift<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> RightShift<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.RightShift(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Conditional Boolean Operations

        public static BinaryExpressionBuilder<T> AndAlso<T>(this ExpressionBuilder<T> left, T right)
        {
            return AndAlso<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> AndAlso<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.AndAlso(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> AndAlso<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return AndAlso<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> AndAlso<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.AndAlso(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<T> OrElse<T>(this ExpressionBuilder<T> left, T right)
        {
            return OrElse<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> OrElse<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.OrElse(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> OrElse<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, Func<T1, T2, TRes> method)
        {
            return OrElse<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), method);
        }
        public static BinaryExpressionBuilder<TRes> OrElse<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, Func<T1, T2, TRes> method)
        {
            return Expression.OrElse(left, right, method.Method);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Comparison Operations

        public static BinaryExpressionBuilder<bool> Equal<T>(this ExpressionBuilder<T> left, T right)
        {
            return Equal<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<bool> Equal<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Equal(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> Equal<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Equal<T1, T2, TRes>(left, ExpressionBuilder.Constant < T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> Equal<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.Equal(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<bool> NotEqual<T>(this ExpressionBuilder<T> left, T right)
        {
            return NotEqual<T>(left, ExpressionBuilder.Constant < T>(right));
        }
        public static BinaryExpressionBuilder<bool> NotEqual<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.NotEqual(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> NotEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return NotEqual<T1, T2, TRes>(left, ExpressionBuilder.Constant < T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> NotEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.NotEqual(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<bool> GreaterThanOrEqual<T>(this ExpressionBuilder<T> left, T right)
        {
            return GreaterThanOrEqual<T>(left, ExpressionBuilder.Constant < T>(right));
        }
        public static BinaryExpressionBuilder<bool> GreaterThanOrEqual<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.GreaterThanOrEqual(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> GreaterThanOrEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return GreaterThanOrEqual(left, ExpressionBuilder.Constant < T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> GreaterThanOrEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.GreaterThanOrEqual(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<bool> GreaterThan<T>(this ExpressionBuilder<T> left, T right)
        {
            return GreaterThan<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<bool> GreaterThan<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.GreaterThan(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> GreaterThan<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return GreaterThan<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> GreaterThan<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.GreaterThan(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<bool> LessThan<T>(this ExpressionBuilder<T> left, T right)
        {
            return LessThan<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<bool> LessThan<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.LessThan(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> LessThan<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return LessThan<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> LessThan<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.LessThan(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        public static BinaryExpressionBuilder<bool> LessThanOrEqual<T>(this ExpressionBuilder<T> left, T right)
        {
            return LessThanOrEqual<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<bool> LessThanOrEqual<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.LessThanOrEqual(left, right);//.ToExpressionBuilder<bool>();
        }

        public static BinaryExpressionBuilder<TRes> LessThanOrEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, T2 right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return LessThanOrEqual<T1, T2, TRes>(left, ExpressionBuilder.Constant<T2>(right), liftToNull, method);
        }
        public static BinaryExpressionBuilder<TRes> LessThanOrEqual<T1, T2, TRes>(this ExpressionBuilder<T1> left, ExpressionBuilder<T2> right, bool liftToNull, Func<T1, T2, TRes> method)
        {
            return Expression.LessThanOrEqual(left, right, liftToNull, method.Method);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Coalescing Operations

        public static BinaryExpressionBuilder<T> Coalesce<T>(this ExpressionBuilder<T> left, T right)
        {
            return Coalesce<T>(left, ExpressionBuilder.Constant<T>(right));
        }
        public static BinaryExpressionBuilder<T> Coalesce<T>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right)
        {
            return Expression.Coalesce(left, right);//.ToExpressionBuilder<T>();
        }

        public static BinaryExpressionBuilder<TRes> Coalesce<T, TRes>(this ExpressionBuilder<T> left, T right, Expression<Func<T, TRes>> conversion)
        {
            return Coalesce<T, TRes>(left, ExpressionBuilder.Constant<T>(right), conversion);
        }
        public static BinaryExpressionBuilder<TRes> Coalesce<T, TRes>(this ExpressionBuilder<T> left, ExpressionBuilder<T> right, Expression<Func<T, TRes>> conversion)
        {
            return Expression.Coalesce(left, right, conversion);//.ToExpressionBuilder<TRes>();
        }

        #endregion

        #region Array Indexing Operations

        public static BinaryExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[]> array, Int32 index)
        {
            return ArrayIndex<T>(array, ExpressionBuilder.Constant<Int32>(index));
        }
        public static BinaryExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[]> array, ExpressionBuilder<Int32> index)
        {
            return Expression.ArrayIndex(array, index);//.ToExpressionBuilder<T>();
        }

        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[,]> array, Int32 index1, Int32 index2)
        {
            return ArrayIndex<T>(array, ExpressionBuilder.Constant<Int32>(index1), ExpressionBuilder.Constant<Int32>(index2));
        }
        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[,]> array, ExpressionBuilder<Int32> index1, ExpressionBuilder<Int32> index2)
        {
            return Expression.ArrayIndex(array, index1, index2);//.ToExpressionBuilder<T>();
        }

        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[, ,]> array, Int32 index1, Int32 index2, Int32 index3)
        {
            return ArrayIndex<T>(array, ExpressionBuilder.Constant<Int32>(index1), ExpressionBuilder.Constant<Int32>(index2), ExpressionBuilder.Constant<Int32>(index3));
        }
        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<T[, ,]> array, ExpressionBuilder<Int32> index1, ExpressionBuilder<Int32> index2, ExpressionBuilder<Int32> index3)
        {
            return Expression.ArrayIndex(array, index1, index2, index3);//.ToExpressionBuilder<T>();
        }

        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<Array> array, params Int32[] indexes)
        {
            return ArrayIndex<T>(array, indexes.Select(i => ExpressionBuilder.Constant<Int32>(i)).ToArray());
        }
        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<Array> array, params ExpressionBuilder<Int32>[] indexes)
        {
            return Expression.ArrayIndex(array, indexes.Select(i => i.Expression).ToArray());//.ToExpressionBuilder<T>();
        }

        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<Array> array, IEnumerable<Int32> indexes)
        {
            return ArrayIndex<T>(array, (IEnumerable<ExpressionBuilder<Int32>>)indexes.Select(i => ExpressionBuilder.Constant<Int32>(i)));
        }
        public static ExpressionBuilder<T> ArrayIndex<T>(this ExpressionBuilder<Array> array, IEnumerable<ExpressionBuilder<Int32>> indexes)
        {
            return Expression.ArrayIndex(array, indexes.Select(i => i.Expression));//.ToExpressionBuilder<T>();
        }

        #endregion
    }
}
